/**
 * 
 */
package org.istt.web.action.ajax;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.istt.domain.AttachFile;
import org.istt.domain.Category;
import org.istt.domain.DocumentType;
import org.istt.domain.Exchange;
import org.istt.domain.ProcessStatus;
import org.istt.domain.SubCategory;
import org.istt.domain.TimeHoliday;
import org.istt.domain.TimeWeekend;
import org.istt.domain.User;
import org.istt.service.AttachFileManager;
import org.istt.service.CategoryManager;
import org.istt.service.DocumentTypeManager;
import org.istt.service.ExchangeManager;
import org.istt.service.FileManager;
import org.istt.service.ProcessStatusManager;
import org.istt.service.SubCategoryManager;
import org.istt.service.TimeHolidayManager;
import org.istt.service.TimeWeekendManager;
import org.istt.service.UserManager;
import org.istt.service.WorkflowManager;
import org.istt.web.NameValuePair;
import org.istt.web.WebConstants;
import org.joda.time.DateMidnight;
import org.joda.time.DateTime;
import org.joda.time.DateTimeConstants;
import org.joda.time.MutableDateTime;
import org.springframework.beans.factory.annotation.Autowired;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

/**
 * @author Huy
 *
 */
public class AjaxAction extends ActionSupport {
	/**
	 * 
	 */
	private static final long serialVersionUID = 4763649519514553240L;
	private AttachFileManager attachFileManager;
	private ProcessStatusManager processMgr;
	private List<AttachFile> attachFiles;
	private List<ProcessStatus> processes;
	private CategoryManager categoryManager;
	private SubCategoryManager subCategoryManager;
	private String cateId;
	private String cateTypeId;
	private String commentId;
	private String currentUserId;
	private String stepName;
	private DateTime fromdate; //created on 03.08.2012
	private List<String> selectedStep;
	private DocumentTypeManager documentTypeManager;
	private List<DocumentType> documentTypes;
	private ExchangeManager exchangeManager;
	private String fieldId;
	private String departmentId;
	public String getDepartmentId() {
		return departmentId;
	}

	public void setDepartmentId(String departmentId) {
		this.departmentId = departmentId;
	}

	private FileManager fileManager;
	private String groupId;
	protected final Log log = LogFactory.getLog(AjaxAction.class);

	private String replyMessage;
	
	private TimeHolidayManager timeHolidayMgr;
	private TimeWeekendManager timeWeekendMgr;
	
	private String userId;
	
	private UserManager userManager;

	private WorkflowManager workflowMgr;

	public String executeGetAttachFileByCatIdAndCatTypeId(){
		attachFiles = attachFileManager.getByCatIdAndCatTypeId(
				NumberUtils.toLong(cateId), 
				NumberUtils.toLong(cateTypeId));
		documentTypes = documentTypeManager.getList();
		return SUCCESS;
	}

	public String executeGetProcessByName(){
//		log.debug("Enter method 'executeGetProcessByName': "+stepName);
		String decodeString = "";
		try {
			decodeString = URLDecoder.decode(this.stepName,"UTF-8");
			log.debug("Enter method 'executeGetProcessByName': "+decodeString);
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if(StringUtils.isNotEmpty(decodeString))  {
			processes = this.processMgr.searchProcessStatus(decodeString);
		}
		return SUCCESS;
	}

	public List<AttachFile> getAttachFiles() {
		return attachFiles;
	}

	/**
	 * @return the attList
	 */
	public List<NameValuePair> getAttList() {
		List<NameValuePair> attList = new ArrayList<NameValuePair>();
		if (!StringUtils.isEmpty(cateId)) {
			if (log.isDebugEnabled()) {
				log.debug("cateId is equal to " + cateId
						+ " getting attached files");
			}

			List<AttachFile> attFiles = attachFileManager.searchByCateId(NumberUtils.toLong(cateId));
			for (AttachFile af : attFiles) {
				NameValuePair elm = new NameValuePair();
				elm.setName(af.getAttachFileName());
				elm.setValue(af.getId() + "");
				attList.add(elm);
			}
		}
		return attList;
	}
	
	public String getCateId() {
		return cateId;
	}

	public String getCateTypeId() {
		return cateTypeId;
	}
	
	/**
	 * @return the catList
	 */
	public List<NameValuePair> getCatList() {
		List<NameValuePair> catList = new ArrayList<NameValuePair>();
		if (!StringUtils.isEmpty(fieldId)) {
			if (log.isDebugEnabled()) {
				log.debug("fieldId is equal to " + fieldId + " getting categories");
			}

			List<Category> categories = categoryManager.getByFieldId(NumberUtils.toLong(fieldId));
			
			for (Category c : categories) {
				NameValuePair elm = new NameValuePair();
				elm.setName(c.getCategoryName());
				/*if(StringUtils.length(c.getCategoryName()) > 80)
					elm.setName(StringUtils.substring(c.getCategoryName(), 0, 80)+"...");
				else
					elm.setName(StringUtils.substring(c.getCategoryName(), 0, 80));*/
				elm.setValue(c.getId() + "");
				catList.add(elm);
			}
		}
		return catList;
	}
	
	public List<NameValuePair> getCategories() {
		List<NameValuePair> catList = new ArrayList<NameValuePair>();
		if (!StringUtils.isEmpty(departmentId)) {
			if (log.isDebugEnabled()) {
				log.debug("departmentId is equal to " + fieldId
						+ " getting categories");
			}

		List<Category> categories = categoryManager.getByDepartmentId(NumberUtils
					.toLong(departmentId));
			for (Category c : categories) {
				NameValuePair elm = new NameValuePair();
				elm.setName(c.getCategoryName());
				/*if(StringUtils.length(c.getCategoryName()) > 80)
					elm.setName(StringUtils.substring(c.getCategoryName(), 0, 80) + "...");
				else
					elm.setName(StringUtils.substring(c.getCategoryName(), 0, 80));*/
				
				elm.setValue(c.getId() + "");
				catList.add(elm);
			}
		}
		return catList;
	}
	
	/**
	 * @return the catList
	 */
	public List<NameValuePair> getSubCatList() {
		List<NameValuePair> catList = new ArrayList<NameValuePair>();
		if (!StringUtils.isEmpty(cateId)) {
			if (log.isDebugEnabled()) {
				log.debug("cateId is equal to " + cateId
						+ " getting subCategories");
			}

			List<SubCategory> subCategories = subCategoryManager.findByCategoryId(NumberUtils
					.toLong(cateId));
			for (SubCategory subCate : subCategories) {
				NameValuePair elm = new NameValuePair();
				elm.setName(subCate.getName());
				elm.setValue(subCate.getId() + "");
				catList.add(elm);
			}
		}
		return catList;
	}

	public String getComment(){
		String comment = "";
		if(!StringUtils.isEmpty(this.commentId)){
			if (log.isDebugEnabled()) {
				log.debug("Enter method getComment || commentId is equal to " + commentId + " getting comments");
			}
			DateFormat dateFormat = new SimpleDateFormat(WebConstants.DATE_TIME_FORMAT);
			
			Exchange message = this.exchangeManager.get(Long.parseLong(this.commentId));
			List<Exchange> lstMsg = this.exchangeManager.getExchangeMessageByFile(message.getFile().getId(), message.getDate());
			for (Iterator<Exchange> iterator = lstMsg.iterator(); iterator.hasNext();) {
				Exchange exchange = (Exchange) iterator.next();
				comment += "<b>"+exchange.getSender().getFullname()+"</b>("+dateFormat.format(exchange.getDate().toDate())+"): <br>"+exchange.getComment() + "<br>";
			}
//			if(message!=null) comment = "<b>"+message.getSender().getFullname()+"</b>: "+message.getComment();
		}
		return comment;
	}
	
	public String getCommentId() {
		return commentId;
	}

	public String getCurrentUserId() {
		return currentUserId;
	}

	public List<DocumentType> getDocumentTypes() {
		return documentTypes;
	}
	
	public String getFieldId() {
		return fieldId;
	}

	public String getGroupId() {
		return groupId;
	}
	
	public List<NameValuePair> getListUser() {
		List<NameValuePair> lstUser = new ArrayList<NameValuePair>();
		if (!StringUtils.isEmpty(groupId)) {
			if (log.isDebugEnabled()) {
				log.debug("groupId is equal to " + groupId + " getting users");
			}
			List<User> lstUsers = new ArrayList<User>();
			lstUsers = userManager.findUserByDeptId(NumberUtils.toLong(groupId));
			for (User u : lstUsers) {
				NameValuePair elm = new NameValuePair();
				elm.setName(u.getFullname());
				elm.setValue(u.getId() + "");
				lstUser.add(elm);
			}
		}
		return lstUser;
	}

	/*public List<NameValuePair> getListUserForExchange() {
		List<NameValuePair> lstUser = new ArrayList<NameValuePair>();
		if (!StringUtils.isEmpty(groupId)) {
			if (log.isDebugEnabled()) {
				log.debug("groupId is equal to " + groupId + " getting users");
			}
			List<User> lstUsers = new ArrayList<User>();
			lstUsers = userManager.findUserByDeptId(NumberUtils.toLong(groupId));
			for (User u : lstUsers) {
				NameValuePair elm = new NameValuePair();
				elm.setName(u.getFullname());
				elm.setValue(u.getId() + "");
				lstUser.add(elm);
			}
		}
		return lstUser;
	}

	public List<NameValuePair> getListUserForTransfer() {
		List<NameValuePair> lstUser = new ArrayList<NameValuePair>();
		if (!StringUtils.isEmpty(groupId)) {
			if (log.isDebugEnabled()) {
				log.debug("groupId is equal to " + groupId + " getting users");
			}
			List<User> lstUsers = new ArrayList<User>();
			lstUsers = userManager.findUserByDeptId(NumberUtils.toLong(groupId));
			for (User u : lstUsers) {
				NameValuePair elm = new NameValuePair();
				elm.setName(u.getFullname());
				elm.setValue(u.getId() + "");
				lstUser.add(elm);
			}
		}
		return lstUser;
	}*/

	public String getMessage(){
		log.debug("enter method getMessage...");
		String result = "";
		User loggedUser = (User)ActionContext.getContext().getSession().get(WebConstants.USER_INFO);
		/*if(!StringUtils.isEmpty(this.currentUserId)){*/
		if(loggedUser!=null){
			
			//User user = this.userManager.get(Long.parseLong(currentUserId));
//			boolean hasNewMsg = this.exchangeManager.checkNewMessage(user.getId(), false);
			boolean hasNewMsg = this.exchangeManager.checkNewMessage(loggedUser.getId(), false);
			
			Date today = new Date();
			
			Calendar tmpEndDate = Calendar.getInstance();
			tmpEndDate.setTime(today);
			tmpEndDate.set(tmpEndDate.get(Calendar.YEAR), tmpEndDate.get(Calendar.MONTH), tmpEndDate.get(Calendar.DAY_OF_MONTH), 00, 00); 
			
			boolean hasNewFile = this.fileManager.checkNewFileByApprover(loggedUser.getId(), tmpEndDate.getTime(), today, false);
			
			if(hasNewMsg) result = result + "msg";
			if(hasNewFile) result = result + "file";
		}
		
		return result;
	}

	public String getReplyMessage() {
		return replyMessage;
	}

	/**
	 * Get the returned date of the file followed by a workflow
	 * @return
	 */
	public String getReturnedDate() {
		if (StringUtils.isEmpty(cateId)) return "";
		Category ct = categoryManager.get(NumberUtils.toLong(cateId));
		double totalDayOfWork = workflowMgr.getTotalDayOfWork(ct.getWorkflow().getId());
		
		//period of time
		DateTime start = new DateMidnight().toDateTime();

		if(fromdate!=null) start = fromdate;
		log.debug("FROM DATE: "+fromdate);
		
		int days = (int)Math.round(totalDayOfWork); //number of days to add
		log.debug("TOTAL DAY OF WORK: "+days);
		
		//how many holidays are between the period of time 
		List<DateTime> lstDt = new ArrayList<DateTime>();
		List<TimeHoliday> timeHolidays = timeHolidayMgr.getList();
		for (TimeHoliday thday : timeHolidays) {
			if (thday.getRepeat()) {
				MutableDateTime mdt = new DateTime(thday.getHolidayDate()).toMutableDateTime();
				mdt.setYear(start.getYear());
				lstDt.add(mdt.toDateTime());
			} else {
				lstDt.add(new DateTime(thday.getHolidayDate()));
			}
		}
		
		//how many days off are between the period of time
		List<TimeWeekend> timeWeekends = timeWeekendMgr.getList();
		int[] dow = new int[]{DateTimeConstants.MONDAY, 
								DateTimeConstants.TUESDAY, 
								DateTimeConstants.WEDNESDAY, 
								DateTimeConstants.THURSDAY, 
								DateTimeConstants.FRIDAY, 
								DateTimeConstants.SATURDAY,
								DateTimeConstants.SUNDAY}; 
		List<Integer> dayOffs = new ArrayList<Integer>();
		for (TimeWeekend tw : timeWeekends) {
			for (int i = 0; i < dow.length; i++) {
				if (dow[i] == tw.getDay_id()) {
					dayOffs.add(dow[i]);
				}
			}
		}
		
		//System.out.println("days = " + days);
		Collections.sort(dayOffs);
		
		/*for (Integer integer : dayOffs) {
			System.out.println("dayoff weekend " + integer);
		}*/
		
		DateTime tmp = start;
		int i = 0;
		for (;true;) {
			tmp = tmp.plusDays(1);
			System.out.print("tmp = " + tmp.toString("dd/MM/yyyy") + " " + tmp.toString("E"));
			
			boolean dayOffInTheWeek = false;
			boolean dayOffInTheHoliday = false;
			//day of week
			for (Integer dayOff : dayOffs) {
				if (tmp.getDayOfWeek() == dayOff) {
					//System.out.print(" ########## tmp.getDayOfWeek() == dayOff : " + (tmp.getDayOfWeek() == dayOff));
					dayOffInTheWeek = true;
					break;
				}
			}
			
			//day, month
			for (DateTime dt : lstDt) {
				if (dt.getDayOfMonth() == tmp.getDayOfMonth() && dt.getMonthOfYear() == tmp.getMonthOfYear()) {
					System.out.print("####### dt.getDayOfMonth() = " + dt.getDayOfMonth());
					System.out.print(" ,tmp.getDayOfMonth() = " + tmp.getDayOfMonth());
					System.out.print(" ,dt.getMonthOfYear() = " + dt.getMonthOfYear());
					System.out.print(" ,tmp.getMonthOfYear() = " + tmp.getMonthOfYear());
					dayOffInTheHoliday = true;
				}
			}
			
			if (dayOffInTheWeek && dayOffInTheHoliday) days++;
			if (!dayOffInTheWeek && !dayOffInTheHoliday) i++;
			
			if (i == days) break;
 		}
		
		
		return tmp.toString("dd/MM/yyyy");
	}

	public String getUserId() {
		return userId;
	}
	
	public void sendMessage(){
		if(!StringUtils.isEmpty(this.commentId) && !StringUtils.isEmpty(this.replyMessage)){
			if (log.isDebugEnabled()) {
				log.debug("enter method sendMessage || commentId is equal to " + commentId + " || message: "+replyMessage);
			}
			Exchange message = this.exchangeManager.get(Long.parseLong(this.commentId));
			if(message!=null){
				
				try {
					message.setStatus(true);
					this.exchangeManager.save(message);
					
					Exchange reply = new Exchange();
					reply.setComment(this.replyMessage);
					reply.setDate(new DateTime());
					reply.setFile(message.getFile());
					User user = (User) ActionContext.getContext().getSession().get(WebConstants.USER_INFO);
					reply.setSender(user);
					reply.setUser(message.getSender());
					reply.setStatus(false);
					this.exchangeManager.save(reply);
					
				} catch (Exception e) {
					// TODO: handle exception
					e.printStackTrace();
				}
			}
		}
	}

	@Autowired
	public void setAttachFileManager(AttachFileManager attachFileManager) {
		this.attachFileManager = attachFileManager;
	}
	
	@Autowired
	public void setCategoryManager(CategoryManager categoryManager) {
		this.categoryManager = categoryManager;
	}
	
	@Autowired
	public void setSubCategoryManager(SubCategoryManager subCategoryManager) {
		this.subCategoryManager = subCategoryManager;
	}

	public void setCateId(String cateId) {
		this.cateId = cateId;
	}	
	
	public void setCateTypeId(String cateTypeId) {
		this.cateTypeId = cateTypeId;
	}
	public void setCommentId(String commentId) {
		this.commentId = commentId;
	}
	
	public void setCurrentUserId(String currentUserId) {
		this.currentUserId = currentUserId;
	}
	
	@Autowired
	public void setDocumentTypeManager(DocumentTypeManager documentTypeManager) {
		this.documentTypeManager = documentTypeManager;
	}
	
	@Autowired
	public void setExchangeManager(ExchangeManager exchangeManager) {
		this.exchangeManager = exchangeManager;
	}
	public void setFieldId(String fieldId) {
		this.fieldId = fieldId;
	}
	@Autowired
	public void setFileManager(FileManager fileManager) {
		this.fileManager = fileManager;
	}
	public void setGroupId(String groupId) {
		this.groupId = groupId;
	}

	public void setReplyMessage(String replyMessage) {
		this.replyMessage = replyMessage;
	}

	@Autowired
	public void setTimeHolidayManager(TimeHolidayManager timeHolidayMgr) {
		this.timeHolidayMgr = timeHolidayMgr;
	}
	
	@Autowired
	public void setTimeWeekendMgr(TimeWeekendManager timeWeekendMgr) {
		this.timeWeekendMgr = timeWeekendMgr;
	}

	public void setUserId(String userId) {
		this.userId = userId;
	}

	@Autowired
	public void setUserManager(UserManager userManager) {
		this.userManager = userManager;
	}

	@Autowired
	public void setWorkflowMgr(WorkflowManager workflowMgr) {
		this.workflowMgr = workflowMgr;
	}

	public void updateStatus(){
		if(!StringUtils.isEmpty(this.commentId)){
			if (log.isDebugEnabled()) {
				log.debug("enter method sendMessage || commentId is equal to " + commentId);
			}
			Exchange message = this.exchangeManager.get(Long.parseLong(this.commentId));
			if(message!=null){
				
				try {
					message.setStatus(true);
					this.exchangeManager.save(message);
					
				} catch (Exception e) {
					// TODO: handle exception
					e.printStackTrace();
				}
			}
		}
	}

	public void setProcesses(List<ProcessStatus> processes) {
		this.processes = processes;
	}

	public List<ProcessStatus> getProcesses() {
		return processes;
	}

	public void setStepName(String stepName) {
		this.stepName = stepName;
	}

	public String getStepName() {
		return stepName;
	}

	@Autowired
	public void setProcessMgr(ProcessStatusManager processMgr) {
		this.processMgr = processMgr;
	}

	public void setSelectedStep(List<String> selectedStep) {
		this.selectedStep = selectedStep;
	}

	public List<String> getSelectedStep() {
		return selectedStep;
	}

	public void setFromdate(DateTime fromdate) {
		this.fromdate = fromdate;
	}

	public DateTime getFromdate() {
		return fromdate;
	}
}
